iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 12
0
Modern Web

Web x Sound - 用 Web 玩轉聲音系列 第 12

Day12 - 自製簡易 DAW (1)

  • 分享至 

  • xImage
  •  

今天先從音量儀表 (Audio Metering) 組件開始做起。為了方便模組化以及開發上比較順手,之後會用 React 來寫,核心功能的程式碼會另外提的,別太擔心。

Audio Meter

https://ithelp.ithome.com.tw/upload/images/20181012/20111876hQeD72vQLn.png
Arrangement View Mixer

這一區都屬於 Mixer (調整音量、相位、mute、solo ... 的地方),今天做的是那兩條綠綠的 bar,音量儀表 (Audio Meter),用來顯示當前的音量大小。

在 Live 內其實有分兩種編輯介面:Arrangement View 與 Session View,前者適合編輯 Audio、MIDI 片段(Clip),後者較適合操作 Loop。Session View 的 Mixer 長得像這樣:

https://ithelp.ithome.com.tw/upload/images/20181012/20111876Z5kggA2gE2.png

仔細分析它的行為,小小一條 meter 會顯示幾種資訊:

  • 左右聲道 (兩條 bar)
  • RMS Level:平均音量 (方均根)(螢光綠實心 bar),這種表示較貼近人耳感受,但對於聲音變化的敏感度較低
  • Peak Level:峰值音量,用來表示瞬間最大值 (最上面的螢光綠小指針) 對聲音變化很敏感
  • 刻度:-90 dB (約略) ~ +6 dB,而且刻度間隔不是固定的
  • 音量超過 0 dB 時會轉紅色

先來切版吧!

切版

https://ithelp.ithome.com.tw/upload/images/20181012/201118765lRE4DM935.png

CodePen

原先想直接用 bootstrap 提供的 progress class 再 ratate 90 度,但發現轉了角度以後,DOM 物件實際佔有的空間不會改變:仍然是橫的,這樣對於組件來說很難使用,所以就自己切了。

props 部分有設計一些可帶入的值調整外觀

Meter.defaultProps = {
  options: {
    range: [-90, 6],
    warnThreshold: 0,
    mainHeight: "200px",
    perWidth: "8px"
  },
  rms: {
    left: 0,
    right: -24
  },
  peak: {
    left: 3,
    right: -18
  }
};

其中會透過一個 function 將 RMS、Peak 數值根據刻度換算後,得出百分比應用到 CSS 中。

// 超過轉紅的
const isOverLoud = (value, options) => value >= options.warnThreshold;

// 數值 -> 刻度換算 -> 百分比,目前只有 數值 -> 百分比
const convertToPercent = (value, options) => {
  // TODO: 計算正確的刻度
  const min = options.range[0];
  const max = options.range[1];
  const ratio = 100 / (max - min);

  if (value >= max) return 100;
  if (value <= min) return 0;

  return (value - min) * ratio;
};

這部分其實是最難的。

在音樂產業中,音量儀表的刻度系統差異很大,根據國家、產業 (流行音樂、電影、影視)、數位/類比...等因素的不同,而有完全不同的刻度標準,連音量 dB 的單位會根據不同領域、不同電壓計算公式,衍生出 dBFS、dBu、dBA、dBV .... 等。有興趣可以參考這張不同刻度系統的比較圖。這邊只好先簡單用線性百分比呈現了...

今天先這樣了~

Reference


上一篇
Day11 - 自製簡易 DAW (0)
下一篇
關於發文的調整
系列文
Web x Sound - 用 Web 玩轉聲音13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言